#ifdef WIN32
	#include <Windows.h>
#endif

//clanlib setup
#include "precomp.h"

//local includes
#include "GameLogic.h"


class Game
{
private:	
	bool quit;
	static const int main_loop_rate = 30;	// 30 ms (30 hz)
public:

	void run()
	{
		quit = false;

		CL_DisplayWindow window("Lunar Lander", 800, 600 );

		CL_Slot slot_quit = window.sig_window_close().connect(this,&Game::on_window_close);

		CL_GraphicContext gc = window.get_gc();
		CL_InputDevice keyboard = window.get_ic().get_keyboard();
		CL_InputDevice mouse = window.get_ic().get_mouse();

#ifdef _DEBUG
		//debugging info
		CL_FontDescription font_desc;
		font_desc.set_typeface_name("tahoma");
		CL_Font_System system_font(gc, font_desc );
#endif
		//initialise game logics
		GameLogic gl;
		gl.init(gc);
		//window.set_size(gl.width, gl.height, true); //set size to fit chessboard
		CL_Slot slot_click = mouse.sig_key_down().connect(&gl, &GameLogic::mouseDown); //register mouse clocks
		CL_Slot slot_down = keyboard.sig_key_down().connect(&gl, &GameLogic::keyDown); // register key down events.
		CL_Slot slot_up = keyboard.sig_key_up().connect(&gl, &GameLogic::keyUp);

		unsigned int last_time = CL_System::get_time();
		unsigned int current_time = CL_System::get_time();
		int time_difference = 0, delta=0;
		while (!quit)
		{
			//Esc closes the game
			if(keyboard.get_keycode(CL_KEY_ESCAPE) == true)
				quit = true;

			//get time difference between now and last render
			current_time = CL_System::get_time();
			time_difference = current_time - last_time;
			if (time_difference > 1000)
				time_difference = 1000;		// Limit the time difference, if the application was paused (eg, moving the window on WIN32)
			delta = time_difference; //delta for moving game objects. in this case 1:1 with time_difference
			last_time = current_time;

			//play game
			//gl.update(delta, keyboard, mouse);
			gl.update(delta);
			
			// ** Enable these 2 lines to display the example magnified **
			//CL_Mat4f matrix = CL_Mat4f::scale( 2.0f,2.0f, 1.0f);
			//gc.set_modelview(matrix);

			gc.clear();

			gl.draw(gc);//draw game objects
						
			window.flip(1); //"1" . The screen is drawn after the next display refresh

			CL_KeepAlive::process(0);
 
			current_time = CL_System::get_time();
			int time_to_sleep_for = main_loop_rate - (current_time - last_time);
			if (time_to_sleep_for > 0)
				CL_System::sleep(time_to_sleep_for);
		}
	}

	void on_window_close()
	{
		quit = true;
	}

};

class DisplayProgram
{
public:
	static int main(const std::vector<CL_String> &args)
	{
		CL_SetupCore setup_core;
		CL_SetupDisplay setup_display;

		#ifdef USE_SOFTWARE_RENDERER
		CL_SetupSWRender setup_swrender;
		#endif

		#ifdef USE_OPENGL_1
		CL_SetupGL1 setup_render;
		#endif

		#ifdef USE_OPENGL_2
		CL_SetupGL setup_render;
		#endif
		
		//CL_SetupSound setup_sound;
		//CL_SoundOutput output(44100);
 
		try
		{
			Game game;
			game.run();
		}
		catch(CL_Exception &exception)
		{
			// Create a console window for text-output if not available
			CL_ConsoleWindow console("Console", 80, 160);
			CL_Console::write_line("Exception caught: " + exception.get_message_and_stack_trace());
			console.display_close_message();
 
			return -1;
		}
 
		return 0;
	}
};
 
// Create global application object, you MUST include this line or the application start-up will fail to locate your application object.
CL_ClanApplication app(&DisplayProgram::main);